<?php
/**
 * Zhub - A PHP Framework For API Developer
 *
 * This file is part of the Zhub package.
 *
 * (c) YiLong Fan <fantiq@163.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @author fanyilong <fantiq@163.com>
 * @copyright 2017 fanyilong. All rights reserved.
 * @package Zhub
 * @date 18-3-5
 */

namespace Zhub\DataBase\Query;

use Zhub\DataBase\Tables\Field;

class Builder
{
    const ORDER_BY_ASC  = 0b1;
    const ORDER_BY_DESC = 0b0;

    const SELECT  = 00;
    const FROM    = 01;
    const JOIN    = 02;
    const GROUP_BY = 03;
    const HAVING  = 04;
    const WHERE   = 05;
    const ORDER_BY = 06;
    const LIMIT   = 07;

    private $sqlComponent = [
        self::SELECT => '',
        self::FROM => '',
        self::JOIN => null,
        self::GROUP_BY => null,
        self::WHERE => null,
        self::ORDER_BY => null,
        self::LIMIT => null,
    ];

    private $parameters = [];

    private $tableName = null;

    public static function table(string $tableName)
    {
        return new self($tableName);
    }

    public function join(string $tableName, $foo, $operator, $bar)
    {
        $this->sqlComponent[self::JOIN] = "LEFT JOIN $tableName ON ";
        return $this;
    }

    public function __construct(string $tableName)
    {
        $this->tableName = $tableName;
        $this->sqlComponent[self::FROM] = "FROM `$tableName`";
    }

    public function select(Field ...$fields)
    {
        foreach ($fields as $idx => $field) {
            $fields[$idx] = "`$this->tableName`.`$field`";
        }
        $select = implode(',', $fields);
        $select = empty($select) ? '*' : $select;
        $this->sqlComponent[self::SELECT] = "SELECT $select";
        return $this;
    }

    public function groupBy(Field $field)
    {
        $this->sqlComponent[self::GROUP_BY] = "GROUP BY $field";
        return $this;
    }

    public function having()
    {
        return $this;
    }

    public function orderBy(Field $field, int $order = self::ORDER_BY_ASC)
    {
        $this->sqlComponent[self::ORDER_BY] = "ORDER BY $field " .
            ($order ? 'ASC' : 'DESC');
        return $this;
    }

    public function limit(int $offset, int $limit = null)
    {
        $this->sqlComponent[self::LIMIT] = "LIMIT $offset" .
            ($limit == null ? '' : ',' . $limit);
        return $this;
    }


    public function where(Condition $condition)
    {
        $this->sqlComponent[self::WHERE] = $condition;
        $this->parameters = $condition->parameters;
    }

    public function toSQL():string
    {
        $sql = '';
        foreach ($this->sqlComponent as $item) {
            if ($item == null) {
                continue;
            }
            $sql .= $item . ' ';
        }
        return trim($sql);
    }

    public function __toString():string
    {
        return $this->toSQL();
    }
}
